Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Approval Usability #172

Merged
merged 11 commits into from
Oct 26, 2024
Merged

Fix: Approval Usability #172

merged 11 commits into from
Oct 26, 2024

Conversation

zacharyblasczyk
Copy link
Member

@zacharyblasczyk zacharyblasczyk commented Oct 25, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced PolicyApprovalRow component to include user information for approvals and improved status rendering.
    • Introduced CollapsibleTableRow for a more interactive TargetReleaseTable, allowing users to expand rows for detailed job data.
  • Bug Fixes

    • Removed handling of pending policy approvals from the ReleasePage, streamlining the user experience.
  • Chores

    • Updated database schema to track user actions related to policy approvals, adding a user_id column and foreign key constraints.

Copy link
Contributor

coderabbitai bot commented Oct 25, 2024

Warning

Rate limit exceeded

@zacharyblasczyk has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 37 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Files that changed from the base of the PR and between c409dc8 and bb7fe9a.

Walkthrough

This pull request implements significant changes across multiple components related to policy approvals and deployment management. The PolicyApprovalRow component has been modified to include user information and improved rendering logic based on approval status. The TargetReleaseTable has been restructured to utilize a new collapsible row component for displaying job data. The ReleasePage component has removed pending approval handling, while the API router has been updated to include user tracking in approval processes. Additionally, database schema changes have been made to support these modifications.

Changes

File Change Summary
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx Updated PolicyApprovalRowProps to include an optional user property and changed environments to environment. Enhanced rendering logic based on approval status.
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx Introduced CollapsibleTableRow component for displaying environment-specific job data. Updated TargetReleaseTable to accept an array of environments.
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/page.tsx Removed handling of pending policy approvals and associated rendering logic.
packages/api/src/router/environment.ts Modified approval router to include optional status and added userId to approval procedures for tracking user actions.
packages/db/drizzle/0024_bouncy_bromley.sql Added user_id column to environment_policy_approval table and created a foreign key constraint linking it to the user table.
packages/db/drizzle/meta/_journal.json Added a new entry to the journal for the database migration related to the new column.
packages/db/src/schema/environment.ts Added userId field to environmentPolicyApproval table and updated imports to include the user entity.
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowPolicyNode.tsx Modified ApprovalDialog to include userId in props and updated approval/rejection logic to incorporate this parameter.

Possibly related PRs

  • fix: Show job external url #154: Involves changes to the PolicyApprovalRow component, directly related to handling approvals and user information.
  • fix: Redeploy to target button #157: Modifies the TargetDropdownMenu and TargetReleaseTable components, relevant to the overall deployment process.
  • fix: External url button #158: Enhances the TargetReleaseTable to include external URLs, potentially interacting with the PolicyApprovalRow.
  • fix: Remove semver and regex release filter #160: Focuses on the release filter logic, which is related to the changes in the main PR that involve the PolicyApprovalRow and its handling of approval statuses.
  • fix: Release dependencies refactor #165: Introduces changes to the CreateRelease component, which may interact with the PolicyApprovalRow component in terms of managing release dependencies and approvals.
  • fix: Target variables #170: Enhances the handling of target variables, which could relate to the user context and approval handling in the main PR, particularly in how approvals are processed in relation to job variables.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (6)
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (2)

28-31: Early return pattern improves error handling.

Good addition of environment validation. However, consider enhancing the error message with more context.

-    logger.error("Environment is undefined for approval:", approval);
+    logger.error("Environment is undefined for approval", {
+      approvalId: approval.id,
+      releaseId: approval.releaseId,
+      policyId: approval.policyId
+    });

112-116: Consider accessibility improvements.

The approval status UI could benefit from ARIA attributes for better screen reader support.

  return (
-   <div className="flex items-center gap-2 rounded-md text-sm">
+   <div 
+     className="flex items-center gap-2 rounded-md text-sm"
+     role="status"
+     aria-label={`Approval status: ${status}`}
+   >
      {renderStatusContent()}
    </div>
  );
packages/api/src/router/environment.ts (3)

165-169: Consider adding error handling for non-existent users

The changes look good, but consider adding error handling for cases where the provided userId doesn't exist.

 .mutation(async ({ ctx, input }) => {
+  const userExists = await ctx.db
+    .select()
+    .from(user)
+    .where(eq(user.id, input.userId))
+    .then(result => result.length > 0);
+
+  if (!userExists) {
+    throw new Error('User not found');
+  }
+
   const envApproval = await ctx.db

Also applies to: 174-174


225-229: Apply consistent error handling for user validation

Similar to the approve procedure, consider adding user existence validation here as well.

 .mutation(({ ctx, input }) =>
   ctx.db.transaction(async (tx) => {
+    const userExists = await tx
+      .select()
+      .from(user)
+      .where(eq(user.id, input.userId))
+      .then(result => result.length > 0);
+
+    if (!userExists) {
+      throw new Error('User not found');
+    }
+
     await tx

Also applies to: 235-235


165-169: Consider extracting user validation to a reusable function

Both approve and reject procedures need similar user validation. Consider extracting this to a reusable function to reduce duplication and ensure consistency.

async function validateUser(db: typeof ctx.db, userId: string) {
  const userExists = await db
    .select()
    .from(user)
    .where(eq(user.id, userId))
    .then(result => result.length > 0);

  if (!userExists) {
    throw new Error('User not found');
  }
}

This function could be used in both procedures before performing the approval/rejection operations.

Also applies to: 225-229

apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (1)

103-105: Simplify key comparison by removing unnecessary String conversion

In the expression (m) => m.key === String(ReservedMetadataKey.Links), the ReservedMetadataKey.Links is already a string. The String() conversion is unnecessary and can be removed to simplify the code.

Apply this diff to simplify the comparison:

const linksMetadata = job.job.metadata.find(
-  (m) => m.key === String(ReservedMetadataKey.Links),
+  (m) => m.key === ReservedMetadataKey.Links,
)?.value;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ec4986d and 8ffa694.

📒 Files selected for processing (7)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (2 hunks)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (3 hunks)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/page.tsx (1 hunks)
  • packages/api/src/router/environment.ts (5 hunks)
  • packages/db/drizzle/0024_bouncy_bromley.sql (1 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
  • packages/db/src/schema/environment.ts (2 hunks)
🧰 Additional context used
🪛 Biome
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx

[error] 101-190: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (13)
packages/db/drizzle/0024_bouncy_bromley.sql (1)

2-6: Review CASCADE DELETE behavior for audit compliance.

The current foreign key constraint will delete approval records when a user is deleted. This could be problematic for audit purposes where you need to maintain a history of who approved what, even if the user no longer exists.

Let's verify if this table is used for audit purposes:

Consider these alternatives:

  1. Use SET NULL instead of CASCADE (requires removing NOT NULL constraint)
  2. Use a soft delete for users to maintain referential integrity
  3. Archive user data instead of deleting it
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/page.tsx (2)

71-71: LGTM: Environment prop addition.

The addition of the environments prop to TargetReleaseTable aligns with the architectural changes, allowing the component to handle environment-specific data and approvals directly.


Line range hint 1-74: Verify the removal of approval handling logic.

The removal of policy approval handling from this component suggests an architectural shift where approval management has been moved to child components. This change could improve separation of concerns, but we should verify that the approval functionality is properly implemented in the new location.

Let's verify the approval handling implementation:

✅ Verification successful

Let me gather more information about the TargetReleaseTable component since the first command failed:


Approval handling has been correctly moved to child components

The removal of approval handling from the page component is a valid architectural improvement. The verification shows that:

  • TargetReleaseTable fetches approvals via api.environment.policy.approval.byReleaseId and passes them to PolicyApprovalRow
  • PolicyApprovalRow handles all approval-related actions (approve/reject) with proper mutations and UI feedback
  • The addition of the environments prop to TargetReleaseTable is necessary as it's used to render environment-specific approvals
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that approval handling has been moved to TargetReleaseTable
# and ensure no approval-related functionality is lost

# Test 1: Check TargetReleaseTable for new approval handling
echo "Checking TargetReleaseTable implementation..."
rg -A 10 "PolicyApprovalRow|approval" --type typescript

# Test 2: Verify no orphaned approval-related code
echo "Checking for any orphaned approval-related code..."
ast-grep --pattern 'api.environment.policy.approval'

Length of output: 1616


Script:

#!/bin/bash
# Check the implementation of TargetReleaseTable and related components
echo "Checking TargetReleaseTable content..."
cat apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx

echo "\nChecking PolicyApprovalRow content..."
cat apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx

Length of output: 10640

apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (1)

17-18: Props refactoring improves type safety.

The props restructuring with optional user info and single environment improves type safety and better reflects the component's requirements.

packages/db/drizzle/meta/_journal.json (1)

172-178: LGTM! Migration journal entry is properly structured.

The new entry follows the established format and maintains sequential ordering.

Let's verify the corresponding migration file exists and contains the expected user tracking changes:

✅ Verification successful

Migration file verified and contains expected changes

The migration file exists at the correct location and implements the expected schema changes:

  • Adds user_id column (UUID) to environment_policy_approval table
  • Sets up foreign key constraint referencing the user table with proper cascade behavior
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify migration file exists and contains user_id column addition

# Test 1: Check if migration file exists
fd "0024_bouncy_bromley.sql" --type f

# Test 2: Verify migration content includes user_id column addition
rg -A 5 "user_id" "packages/db/drizzle/0024_bouncy_bromley.sql"

Length of output: 503

packages/db/src/schema/environment.ts (1)

22-22: LGTM!

The import is correctly placed and follows the established import pattern.

packages/api/src/router/environment.ts (2)

34-34: LGTM: Import added for user schema

The addition of the user schema import aligns with the new user tracking functionality.


126-126: Verify impact of optional status on existing consumers

The changes to make status optional and include user information look good, but we should verify the impact on existing consumers of this API.

Also applies to: 137-137, 140-145, 152-152

✅ Verification successful

Making status optional is safe for existing consumers

Based on the codebase analysis:

  1. The database schema maintains status as NOT NULL with a default value of 'pending'
  2. Frontend components handle the status properly:
    • TargetReleaseTable.tsx safely filters and types the approvals data
    • FlowPolicyNode.tsx has proper null checks and status handling
  3. The job dispatcher correctly checks status with environment_policy_approval?.status === "approved"

Making the status optional in the input schema while keeping it required in the database (with a default) is a safe change that won't impact existing consumers.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for direct usage of byReleaseId to verify consumers handle optional status
rg -A 5 "byReleaseId.*status.*" --type ts

Length of output: 43


Script:

#!/bin/bash
# Let's first find all references to byReleaseId function
rg -A 5 "byReleaseId" --type ts

# Also search for any router endpoints that might be consuming this
rg -A 5 "router\.(get|post|put|delete).*release.*approval" --type ts

# Let's also check the schema usage
ast-grep --pattern 'z.enum(["pending", "approved", "rejected"])'

Length of output: 7179


Script:

#!/bin/bash
# Let's check how the approval data is being used in the frontend components
rg -B 5 -A 10 "environmentApprovals" --type tsx

# Also check for any direct status handling
rg -B 2 -A 5 "approval.*status" --type tsx

Length of output: 148


Script:

#!/bin/bash
# Let's check how the approval data is being used in the frontend components, without file type restriction
rg -B 5 -A 10 "environmentApprovals"

# Also check for any direct status handling
rg -B 2 -A 5 "approval.*status"

# Let's also check the component that uses the byReleaseId query
rg -B 10 -A 10 "policy\.approval\.byReleaseId\.useQuery"

Length of output: 45790

apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (5)

72-97: Great implementation of collapsible environment rows

The use of useState for controlling the expansion of environment rows and the clean rendering logic enhance the user experience by making the interface more interactive and intuitive.


100-191: Conditional rendering is handled correctly

The conditional rendering of job details based on the isExpanded state is implemented well. The mapping over jobs to display each job's information ensures that users can access detailed data when needed.

🧰 Tools
🪛 Biome

[error] 101-190: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


89-96: Proper handling of policy approvals

Displaying policy approvals using the PolicyApprovalRow component with appropriate props ensures that approval statuses are accurately represented for each environment.


148-168: Robust handling of external links

The code safely renders external links with the correct target and rel attributes, which is important for security and preventing potential vulnerabilities like reverse tabnabbing.


Line range hint 196-221: Efficient rendering of TargetReleaseTable

Iterating over environments to render CollapsibleTableRow components makes the TargetReleaseTable dynamic and scalable for multiple environments.

🧰 Tools
🪛 Biome

[error] 101-190: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

zacharyblasczyk and others added 5 commits October 25, 2024 02:46
…eployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Zachary Blasczyk <[email protected]>
@zacharyblasczyk
Copy link
Member Author

@coderabbitai Please re-review the code. I want to keep the userId nullable because it is only set when keeping track of the approver/rejector.

Copy link
Contributor

coderabbitai bot commented Oct 25, 2024

@zacharyblasczyk: Understood, I will re-review the code considering your decision to keep userId nullable since it is only set when tracking the approver/rejector.

(=・ω・=)?


✏️ Learnings added
Learnt from: zacharyblasczyk
URL: https://github.com/ctrlplanedev/ctrlplane/pull/172

Timestamp: 2024-10-25T10:00:58.926Z
Learning: In the approval process, the `userId` field is kept nullable because it is only set when tracking the approver or rejector.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8ffa694 and 132540a.

📒 Files selected for processing (3)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowPolicyNode.tsx (3 hunks)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (3 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx
  • packages/db/drizzle/meta/_journal.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (1)

27-30: Replace console.error with proper error logging.

While the validation is good, using console.error in production code isn't recommended.

Consider using a proper error logging system or error boundary:

  if (!environment) {
-   console.error("Environment is undefined for approval:", approval);
+   // TODO: Replace with your error logging system
+   logger.error("Environment is undefined for approval", { approval });
    return null;
  }
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (2)

43-58: Consider adding loading state for approvals query.

While there's a loading state for jobs, the approvals query loading state isn't handled. This could lead to a jarring user experience if approvals load after the component is rendered.

Consider showing a loading indicator or skeleton for approvals while they're loading:

+ if (approvals.isLoading) {
+   return (
+     <div className="flex items-center gap-2">
+       <IconLoader2 className="h-4 w-4 animate-spin" />
+     </div>
+   );
+ }

Line range hint 37-190: Consider memoizing the CollapsibleTableRow component.

The component could benefit from memoization to prevent unnecessary re-renders, especially when multiple rows are rendered.

Consider wrapping the component with React.memo:

-const CollapsibleTableRow: React.FC<CollapsibleTableRowProps> = ({
+const CollapsibleTableRow = React.memo(function CollapsibleTableRow({
   environment,
   deploymentName,
   release,
-}) => {
+}: CollapsibleTableRowProps) {
   // ... existing code
-};
+});
🧰 Tools
🪛 Biome

[error] 97-186: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 132540a and c409dc8.

📒 Files selected for processing (3)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (3 hunks)
  • apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (3 hunks)
  • packages/api/src/router/environment.ts (5 hunks)
🧰 Additional context used
🪛 Biome
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx

[error] 97-186: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (11)
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/PolicyApprovalRow.tsx (5)

6-6: LGTM: Type changes improve type safety.

The updated types properly reflect the nullable user information and single environment requirement.

Also applies to: 16-17


32-34: LGTM: Clean variable declarations.

The destructuring and data fetching logic is well-organized.


42-42: LGTM: Improved user feedback messages.

The toast messages now properly reference the environment name and provide clear feedback.

Also applies to: 53-53


58-69: LGTM: Concise action handlers.

The mutation handlers are well-structured and maintain consistent behavior.


72-97: 🛠️ Refactor suggestion

Consider extracting status-specific components.

I agree with the previous review comment about moving these to their own components. This would improve maintainability and reusability.

Consider this structure:

const PendingActions: React.FC<{ onApprove: () => void; onReject: () => void }> = ...
const ApprovalStatus: React.FC<{ status: string; userName?: string }> = ...

// In main component
return (
  <div className="flex items-center gap-2 rounded-md text-sm">
    {status === "pending" ? (
      <PendingActions onApprove={handleApprove} onReject={handleReject} />
    ) : (
      <ApprovalStatus status={status} userName={approval.user?.name} />
    )}
  </div>
);
apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/TargetReleaseTable.tsx (3)

Line range hint 3-34: LGTM! Well-structured type definitions and imports.

The type definitions are clear and properly typed, with good organization of imports.


192-216: LGTM! Clean implementation of the table wrapper.

The component is well-structured and properly handles the mapping of environments to CollapsibleTableRow components.


97-187: ⚠️ Potential issue

Remove unnecessary Fragment wrapper.

The Fragment wrapper around the conditional rendering is redundant since it contains only one child.

Replace the Fragment with the direct conditional rendering:

-      {isExpanded && (
-        <>
+      {isExpanded && jobs?.map((job, idx) => {
         // ... existing code
-        </>
-      )}
+      })}

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome

[error] 97-186: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

packages/api/src/router/environment.ts (3)

34-34: LGTM: User schema import added correctly

The import is properly placed and will support the new user tracking functionality.


Line range hint 126-152: LGTM: Enhanced query flexibility and user tracking

The changes improve the query flexibility by making the status filter optional and properly integrate user tracking through a left join. The nullable user relationship aligns with the PR objective of tracking approvers/rejectors.


225-235: LGTM: Consistent user tracking in rejection process

The changes maintain consistency with the approval process by implementing the same user tracking pattern while preserving the existing transaction and job cancellation logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants